Il est souvent nécessaire d’utiliser des techniques de visualisation à toutes les étapes d’une étude statistique. Un des avantages de R est qu’il est relativement simple de mettre en oeuvre tout les types de graphes généralement utilisés. Dans cette fiche, nous présentons tout d’abord les fonctions classiques qui permettent de tracer des figures. Nous proposons ensuite une introduction aux graphes ggplot qui sont de plus en plus utilisés pour faire de la visualisation.
Pour commencer il est intéressant d’examiner quelques exemples de représentations graphiques construits avec R. On peut les obtenir à l’aide de la fonction demo.
demo(graphics)
C’est une fonction générique que l’on peut utiliser pour représenter différents types de données. L’utilisation standard consiste à visualiser une variable y en fonction d’une variable x. On peut par exemple obtenir le graphe de la fonction \(x\mapsto \sin(2\pi x)\) sur \([0,1]\), à l’aide de
x <- seq(-2*pi,2*pi,by=0.05)
y <- sin(x)
plot(x,y) #points (par défaut)
plot(x,y,type="l") #représentation sous forme de ligne
Nous proposons des exemples de représentations de variables quantitatives et qualitatives à l’aide du jeu de données ozone.txt que l’on importe avec
ozone <- read.table("ozone.txt")
summary(ozone)
## maxO3 T9 T12 T15
## Min. : 42.00 Min. :11.30 Min. :14.00 Min. :14.90
## 1st Qu.: 70.75 1st Qu.:16.20 1st Qu.:18.60 1st Qu.:19.27
## Median : 81.50 Median :17.80 Median :20.55 Median :22.05
## Mean : 90.30 Mean :18.36 Mean :21.53 Mean :22.63
## 3rd Qu.:106.00 3rd Qu.:19.93 3rd Qu.:23.55 3rd Qu.:25.40
## Max. :166.00 Max. :27.00 Max. :33.50 Max. :35.50
## Ne9 Ne12 Ne15 Vx9
## Min. :0.000 Min. :0.000 Min. :0.00 Min. :-7.8785
## 1st Qu.:3.000 1st Qu.:4.000 1st Qu.:3.00 1st Qu.:-3.2765
## Median :6.000 Median :5.000 Median :5.00 Median :-0.8660
## Mean :4.929 Mean :5.018 Mean :4.83 Mean :-1.2143
## 3rd Qu.:7.000 3rd Qu.:7.000 3rd Qu.:7.00 3rd Qu.: 0.6946
## Max. :8.000 Max. :8.000 Max. :8.00 Max. : 5.1962
## Vx12 Vx15 maxO3v vent pluie
## Min. :-7.878 Min. :-9.000 Min. : 42.00 Est :10 Pluie:43
## 1st Qu.:-3.565 1st Qu.:-3.939 1st Qu.: 71.00 Nord :31 Sec :69
## Median :-1.879 Median :-1.550 Median : 82.50 Ouest:50
## Mean :-1.611 Mean :-1.691 Mean : 90.57 Sud :21
## 3rd Qu.: 0.000 3rd Qu.: 0.000 3rd Qu.:106.00
## Max. : 6.578 Max. : 5.000 Max. :166.00
On visualise tout d’abord 2 variables quantitatives à l’aide d’un nuage de points : la concentration en ozone maximale maxO3 en fonction de la température à 12h T12.
plot(ozone[,"T12"],ozone[,"maxO3"])
Comme les deux variables appartiennent au même jeu de données, on peut obtenir la même représentation à l’aide d’une sytaxe plus claire qui ajoutent automatiquement les noms des variables sur les axes :
plot(maxO3~T12,data=ozone)
Une autre façon de faire (moins naturelle) :
plot(ozone[,"T12"],ozone[,"maxO3"],xlab="T12",ylab="maxO3")
Il existe des fonctions spécifiques pour chaque type de graphs, par exemple histogram, barplot et boxplot :
hist(ozone$maxO3,main="Histogram")
barplot(table(ozone$vent)/nrow(ozone),col="blue")
boxplot(maxO3~vent,data=ozone)
On peut utiliser ce package pour obtenir des graphes dynamiques. L’utilisation est relativement simple, il suffit d’ajouter le prefixe am devant le nom de la fonction :
library(rAmCharts)
amHist(ozone$maxO3)
amPlot(ozone,col=c("T9","T12"))
amBoxplot(maxO3~vent,data=ozone)
x <- seq(0,2*pi,length=1000)
plot(x,sin(x),type="l")
title("Représentation de la fonction sinus")
x <- seq(-4,4,by=0.01)
plot(x,dnorm(x),type="l")
abline(v=0,lty=2)
lines(x,dt(x,5),col=2)
lines(x,dt(x,30),col=3)
legend("topleft",legend=c("normal","Student(5)","Student(30)"),col=1:3,lty=1)
taches <- read.table("taches_solaires.csv",sep=";",header=TRUE,dec=",")
library(tidyverse)
periode <- cut_interval(taches$annee,n=8)
couleurs <- c("yellow", "magenta", "orange", "cyan", "grey", "red", "green", "blue")
levels(periode) <- couleurs
coordx <- seq(along=taches[,1])
On crée une séquence avec un pas de 1 de longueur égale à la dimension de taches[,1].
plot(coordx,taches[,1],xlab="Temps",ylab="Nombre de taches",col=periode,type="p",pch="+")
On reprend le jeu de données sur l’ozone. A l’aide de la fonction layout séparer la fenêtre graphique en deux lignes avec
layout(matrix(c(1,1,2,3), 2, 2, byrow = TRUE))
plot(maxO3~T12,data=ozone)
hist(ozone$T12)
boxplot(ozone$maxO3)
Ce package propose de définir des graphes sur R en utilisant une grammaire des graphiques (tout comme dplyr pour manipuler les données). On peut trouver de la documentation sur ce package ici. Nous considérons un sous échantillon du jeu de données diamonds du package ggplot2 (qui se trouve dans le tidyverse).
library(tidyverse)
set.seed(1234)
diamonds2 <- diamonds[sample(nrow(diamonds),5000),]
summary(diamonds2)
## carat cut color clarity depth
## Min. :0.2000 Fair : 158 D: 640 SI1 :1189 Min. :43.00
## 1st Qu.:0.4000 Good : 455 E: 916 VS2 :1157 1st Qu.:61.10
## Median :0.7000 Very Good:1094 F: 900 SI2 : 876 Median :61.80
## Mean :0.7969 Premium :1280 G:1018 VS1 : 738 Mean :61.76
## 3rd Qu.:1.0400 Ideal :2013 H: 775 VVS2 : 470 3rd Qu.:62.50
## Max. :4.1300 I: 481 VVS1 : 326 Max. :71.60
## J: 270 (Other): 244
## table price x y
## Min. :49.00 Min. : 365 Min. : 0.000 Min. :3.720
## 1st Qu.:56.00 1st Qu.: 945 1st Qu.: 4.720 1st Qu.:4.720
## Median :57.00 Median : 2376 Median : 5.690 Median :5.700
## Mean :57.43 Mean : 3917 Mean : 5.728 Mean :5.731
## 3rd Qu.:59.00 3rd Qu.: 5294 3rd Qu.: 6.530 3rd Qu.:6.520
## Max. :95.00 Max. :18757 Max. :10.000 Max. :9.850
##
## z
## Min. :0.000
## 1st Qu.:2.920
## Median :3.520
## Mean :3.538
## 3rd Qu.:4.030
## Max. :6.430
##
help(diamonds)
Pour un jeu de données considéré, un graphe ggplot est défini à partir de couches. Il faut a minima spécifier :
Il existe un verbe pour définir chacune de ces couches :
On peut obtenir le nuage de points carat vs price avec la fonction plot :
plot(price~carat,data=diamonds2)
Avec ggplot, on va faire
ggplot(diamonds2) #rien
ggplot(diamonds2)+aes(x=carat,y=price) #rien
ggplot(diamonds2)+aes(x=carat,y=price)+geom_point() #bon
ggplot(diamonds2)+aes(x=carat)+geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(diamonds2)+aes(x=carat)+geom_histogram(bins=10)
ggplot(diamonds2)+aes(x=cut)+geom_bar()
La syntaxe ggplot se construit à partir d’éléments indépendants qui définissent la grammaire de ggplot. Les principaux verbes sont :
Data et aestheticsCes deux éléments renseignent les données et les variables à représenter. Par exemple, pour le nuage de points price vs carat on fera
ggplot(diamonds2)+aes(x=carat,y=price)
On peut aussi utiliser les arguments color, size, fill dans la fonction aes lorsque des couleurs ou des tailles sont définies par des variables du jeu de données. Par exemple
ggplot(diamonds2)+aes(x=carat,y=price,color=cut)
GeometricsUtile pour décrire le type de représentations. Pour un nuage de points, on utilisera par exemple geom_point :
ggplot(diamonds2)+aes(x=carat,y=price,color=cut)+geom_point()
On observe que ggplot ajoute la légende automatiquement. Voici quelques exemples de geometrics :
| Geom | Description | Aesthetics |
|---|---|---|
| geom_point() | nuage de points | x, y, shape, fill |
| geom_line() | Ligne (ordonnée selon x) | x, y, linetype |
| geom_abline() | Ligne | slope, intercept |
| geom_path() | Ligne (ordonnée par l’index) | x, y, linetype |
| geom_text() | Texte | x, y, label, hjust, vjust |
| geom_rect() | Rectangle | xmin, xmax, ymin, ymax, fill, linetype |
| geom_polygon() | Polygone | x, y, fill, linetype |
| geom_segment() | Segment | x, y, fill, linetype |
| geom_bar() | Diaggramme en barres | x, fill, linetype, weight |
| geom_histogram() | Histogramme | x, fill, linetype, weight |
| geom_boxplot() | Boxplot | x, y, fill, weight |
| geom_density() | Densité | x, y, fill, linetype |
| geom_contour() | Lignes de contour | x, y, fill, linetype |
| geom_smooth() | Lisseur (linéaire ou non linéaire) | x, y, fill, linetype |
| Tous | color, size, group |
ggplot(diamonds2)+aes(x=cut)+geom_bar(fill="blue")
ggplot(diamonds2)+aes(x=cut,fill=cut)+geom_bar()
On peut aussi spécifier les couleurs directement
ggplot(diamonds2)+aes(x=cut)+geom_bar(fill=c("blue","red","green","yellow","black"))
Statistics (partie optionnelle)Certains graphes nécessitent des calculs d’indicateurs statistiques, comme par exemple le diagamme en barres ou l’histogramme où il faut calculer des hauteurs. Les transformations simples peuvent se faire rapidement, on peut par exemple tracer la fonction sinus avec
D <- data.frame(X=seq(-2*pi,2*pi,by=0.01))
ggplot(D)+aes(x=X,y=sin(X))+geom_line()
La transformation est précisée dans la fonction aes. Pour des transformations plus complexes, nous devons utiliser des statistics. Une fonction stat permet de définir des nouvelles variables à partir du jeu de données initial, il est ensuite possible de représenter ces nouvelles variables. Par exemple, la fonction stat_bin, qui est utilisée par défaut pour construire des histogrammes, produit les variables suivantes :
count, le nombre d’observations dans chaque classes.density, la valeur de la densité des observations dans chaque classe (fréquance divisée par largeur de la classe).x, le centre de la classe.Par défaut geom_histogram représente sur l’axe \(y\) le nombre d’observations dans chaque classe (la variable count).
ggplot(diamonds)+aes(x=price)+geom_histogram(bins=40)
Si on souhaite visualiser la densité, il faudra utiliser
ggplot(diamonds)+aes(x=price,y=..density..)+geom_histogram(bins=40)
Il est possible d’utiliser les fonctions stat_ à la place des geom_ pour certaines représentations. Chaque fonction stat_ possède par défaut un geom_ et réciproquement. Par exemple,
ggplot(diamonds2)+aes(x=carat,y=price)+geom_smooth(method="loess")
ggplot(diamonds2)+aes(x=carat,y=price)+stat_smooth(method="loess")
produisent le même graphe. On peut changer certaines options graphiques dans les fonctions stat_ en utilisant l’option geom :
ggplot(diamonds2)+aes(x=carat,y=price)+stat_smooth(method="loess",geom="point")
Voici quelques exemple de fonctions stat_
| Stat | Description | Paramètres |
|---|---|---|
| stat_identity() | aucune transformation | |
| stat_bin() | Count | binwidth, origin |
| stat_density() | Density | adjust, kernel |
| stat_smooth() | Smoother | method, se |
| stat_boxplot() | Boxplot | coef |
stat et geom ne sont pas toujours simples à combiner. Nous recommandons d’utiliser geom lorsqu’on débute avec ggplot.
On considère une variable qualitative \(X\) dont la loi est donnée par \[P(X=red)=0.3,\ P(X=blue)=0.2,\ P(X=green)=0.4,\ P(X=black)=0.1\] Tracer le digramme en barres associé à cette distribution.
X <- data.frame(X1=c("red","blue","green","black"),X2=c(0.3,0.2,0.4,0.1))
ggplot(X)+aes(x=X1,y=X2,fill=X1)+geom_bar(stat="identity")
ScalesLes échelles (scales) controlent certaines options pour les variables utilisées dans aes (changement de couleurs, de tailles…). On utilise généralement ce verbe à la dernière étape de construction du graphe. La syntaxe est définie comme suit :
Par exemple,
ggplot(diamonds2)+aes(x=carat,y=price,color=cut)+geom_point()+
scale_color_manual(values=c("Fair"="black","Good"="yellow",
"Very Good"="blue","Premium"="red","Ideal"="green"))
Voici quelques exemples des principales échelles :
| aes | Discret | Continu |
|---|---|---|
| Couleur (color et fill) | brewer | gradient |
| - | grey | gradient2 |
| - | hue | gradientn |
| - | identity | |
| - | manual | |
| Position (x et y) | discrete | continous |
| - | date | |
| Forme | shape | |
| - | identity | |
| - | manual | |
| Taille | identity | size |
| - | manual |
Nous présentons maintenant quelques exemples :
Couleur dans un diagramme en barresp1 <- ggplot(diamonds2)+aes(x=cut)+geom_bar(aes(fill=cut))
p1
On change la couleur en utilisant la palette Purples :
p1+scale_fill_brewer(palette="Purples")
Gradient de couleurs pour un nuage de points :p2 <- ggplot(diamonds2)+aes(x=carat,y=price)+geom_point(aes(color=depth))
p2
On change le gradient de couleur
p2+scale_color_gradient(low="red",high="yellow")
Modification sur les axesp2+scale_x_continuous(breaks=seq(0.5,3,by=0.5))+scale_y_continuous(name="prix")+scale_color_gradient("Profondeur")
Group et facetsggplot permet de faire des représentations pour des groupes d’individus. Il est possible de procéder de deux façons différentes :
Représentons ici (sur le même graphe) le lisseur price vs carat pour chaque modalité de cut
ggplot(diamonds2)+aes(x=carat,y=price,group=cut,color=cut)+geom_smooth(method="loess")
Pour obtenir cette représentation sur plusieurs fenêtres, on utilise
ggplot(diamonds2)+aes(x=carat,y=price)+geom_smooth(method="loess")+facet_wrap(~cut)
ggplot(diamonds2)+aes(x=carat,y=price)+geom_smooth(method="loess")+facet_wrap(~cut,nrow=1)
facet_grid et facet_wrap font des choses proches mais divisent la fenêtre de façon différente :
ggplot(diamonds2)+aes(x=carat,y=price)+geom_point()+geom_smooth(method="lm")+facet_grid(color~cut)
ggplot(diamonds2)+aes(x=carat,y=price)+geom_point()+geom_smooth(method="lm")+facet_wrap(color~cut)
La syntaxe ggplot est définie selon le schéma :
ggplot()+aes()+geom_()+scale_()
Elle est très flexible, on peut par exemple spécifier les aes dans les verbes ggplot ou geom_ :
ggplot(diamonds2)+aes(x=carat,y=price)+geom_point()
ggplot(diamonds2,aes(x=carat,y=price))+geom_point()
ggplot(diamonds2)+geom_point(aes(x=carat,y=price))
Ceci peut se révéler très utile lorsqu’on utilise des aes différents dans les geom_.
On peut aussi construire un graphe à l’aide de différents jeux de données :
X <- seq(-2*pi,2*pi,by=0.001)
Y1 <- cos(X)
Y2 <- sin(X)
donnees1 <- data.frame(X,Y1)
donnees2 <- data.frame(X,Y2)
ggplot(donnees1)+geom_line(aes(x=X,y=Y1))+
geom_line(data=donnees2,aes(x=X,y=Y2),color="red")
Il existe d’autres fonctions ggplot :
p <- ggplot(diamonds2)+aes(x=carat,y=price,color=cut)+geom_point()
p+theme_bw()
p+theme_classic()
p+theme_grey()
p+theme_bw()
X <- seq(-2*pi,2*pi,by=0.001)
Y1 <- cos(X)
Y2 <- sin(X)
donnees1 <- data.frame(X,Y1)
donnees2 <- data.frame(X,Y2)
ggplot(donnees1)+geom_line(aes(x=X,y=Y1))+
geom_line(data=donnees2,aes(x=X,y=Y2),color="red")
donnees <- data.frame(X,Y1,Y2)
ggplot(donnees)+aes(x=X,y=Y1)+geom_line()+geom_line(aes(y=Y2),color="red")
df <- data.frame(X,cos=Y1,sin=Y2)
df1 <- gather(df,key="func",value="value",-X)
#ou
df1 <- gather(df,key="func",value="value",cos,sin)
ggplot(df1)+aes(x=X,y=value,color=func)+geom_line()
ggplot(df1)+aes(x=X,y=value)+geom_line()+facet_wrap(~func)
library(gridExtra)
p1 <- ggplot(donnees1)+aes(x=X,y=Y1)+geom_line()
p2 <- ggplot(donnees2)+aes(x=X,y=Y2)+geom_line()
grid.arrange(p1,p2,nrow=1)
On considère les données mtcars
data(mtcars)
summary(mtcars)
## mpg cyl disp hp
## Min. :10.40 Min. :4.000 Min. : 71.1 Min. : 52.0
## 1st Qu.:15.43 1st Qu.:4.000 1st Qu.:120.8 1st Qu.: 96.5
## Median :19.20 Median :6.000 Median :196.3 Median :123.0
## Mean :20.09 Mean :6.188 Mean :230.7 Mean :146.7
## 3rd Qu.:22.80 3rd Qu.:8.000 3rd Qu.:326.0 3rd Qu.:180.0
## Max. :33.90 Max. :8.000 Max. :472.0 Max. :335.0
## drat wt qsec vs
## Min. :2.760 Min. :1.513 Min. :14.50 Min. :0.0000
## 1st Qu.:3.080 1st Qu.:2.581 1st Qu.:16.89 1st Qu.:0.0000
## Median :3.695 Median :3.325 Median :17.71 Median :0.0000
## Mean :3.597 Mean :3.217 Mean :17.85 Mean :0.4375
## 3rd Qu.:3.920 3rd Qu.:3.610 3rd Qu.:18.90 3rd Qu.:1.0000
## Max. :4.930 Max. :5.424 Max. :22.90 Max. :1.0000
## am gear carb
## Min. :0.0000 Min. :3.000 Min. :1.000
## 1st Qu.:0.0000 1st Qu.:3.000 1st Qu.:2.000
## Median :0.0000 Median :4.000 Median :2.000
## Mean :0.4062 Mean :3.688 Mean :2.812
## 3rd Qu.:1.0000 3rd Qu.:4.000 3rd Qu.:4.000
## Max. :1.0000 Max. :5.000 Max. :8.000
ggplot(mtcars)+aes(x=mpg)+geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
ggplot(mtcars)+aes(x=mpg)+geom_histogram(bins=10)
2.Tracer l’histogramme de la densité.
ggplot(mtcars)+aes(x=mpg,y=..density..)+geom_histogram(bins=10)
ggplot(mtcars)+aes(x=cyl)+geom_bar()
ggplot(mtcars)+aes(x=disp,y=mpg,color=cyl)+geom_point()
ggplot(mtcars)+aes(x=disp,y=mpg,color=as.factor(cyl))+geom_point()
ggplot(mtcars)+aes(x=disp,y=mpg,color=as.factor(cyl))+geom_point()
ggplot(mtcars)+aes(x=disp,y=mpg,color=as.factor(cyl))+
geom_point()+geom_smooth(method="lm")
n <- 100
X <- runif(n)
eps <- rnorm(n,sd=0.2)
Y <- 3+X+eps
D <- data.frame(X,Y)
model <- lm(Y~.,data=D)
co <- coef(model)
D$fit <- predict(model)
co <- coef(lm(Y~.,data=D))
ggplot(D)+aes(x=X,y=Y)+geom_point()+
geom_abline(slope=co[2],intercept=co[1],color="blue")
#2nd method
ggplot(D)+aes(x=X,y=Y)+geom_point()+geom_smooth(method="lm")
3. Représenter les résidus : on ajoutera une ligne verticale entre chaque point et la droite de lissage (utiliser geom_segment).
ggplot(D)+aes(x=X,y=Y)+geom_point()+
geom_smooth(method="lm")+geom_segment(aes(xend=X,yend=fit))
On considère les données diamonds.
ggplot(data=diamonds) + geom_boxplot(aes(x=cut,y=carat,fill=cut))
ggplot(data=diamonds) +
geom_boxplot(aes(x=cut,y=carat,fill=cut))+coord_flip()
ggplot(data=diamonds) + geom_density(aes(x=carat,y=..density..)) +
facet_grid(cut~.)
Q1 <- diamonds %>% group_by(cut) %>%
summarize(q1=quantile(carat,c(0.25)),q2=quantile(carat,c(0.5)),q3=quantile(carat,c(0.75)))
quantildf <- Q1%>% gather(key="alpha",value="quantiles",-cut)
ggplot(data=diamonds) + geom_density(aes(x=carat,y=..density..)) +
facet_grid(cut~.) +
geom_vline(data=quantildf,aes(xintercept=quantiles),col=alpha("black",1/2))
library(ggstance)
ggplot(data=diamonds) +
geom_boxploth(data=diamonds,aes(y=-0.5,x=carat,fill=cut)) +
geom_density(aes(x=carat,y=..density..)) +
facet_grid(cut~.) +
geom_vline(data=quantildf,aes(xintercept=quantiles),col=alpha("black",1/2))
On considère les données tennis sur les tournois du grand chelem disponibles ici https://archive.ics.uci.edu/ml/datasets/Tennis+Major+Tournament+Match+Statistics.
FrenchOpen_men_2013 <- read_csv("FrenchOpen-men-2013.csv")
RG2013 <- FrenchOpen_men_2013
WIMB2013 <- read_csv("Wimbledon-men-2013.csv")
RG_WIMB2013 <- bind_rows("RG"=RG2013,"WIMB"=WIMB2013,.id="Tournament")
RG_WIMB2013 %>% mutate(nb_aces=ACE.1+ACE.2) %>% ggplot()+aes(x=nb_aces,color=Tournament,fill=Tournament)+geom_histogram(bins=15)+facet_wrap(~Tournament,nrow=2)
RG_WIMB2013 %>% mutate(nb_aces=ACE.1+ACE.2) %>%
ggplot()+aes(y=nb_aces,x=Tournament)+geom_boxplot()
RG_WIMB2013 %>% mutate(NPA=NPA.1+NPA.2) %>%
ggplot()+aes(y=NPA,x=Tournament)+geom_boxplot()
df <- RG2013 %>% select(Player1,Player2,Result,FSP.1,FSP.2) %>%
mutate(FSP.W=FSP.1*(Result==1)+FSP.2*(Result==0),FSP.L=FSP.1*(Result==0)+FSP.2*(Result==1))
df1 <- df %>% select(FSP.W,FSP.L) %>% gather(key=Result,value=FSP)
ggplot(df1)+aes(x=Result,y=FSP)+geom_boxplot()
df <- WIMB2013 %>% select(Player1,Player2,Result,FSP.1,FSP.2) %>%
mutate(FSP.W=FSP.1*(Result==1)+FSP.2*(Result==0),FSP.L=FSP.1*(Result==0)+FSP.2*(Result==1))
df1 <- df %>% select(FSP.W,FSP.L) %>% gather(key=Result,value=FSP)
ggplot(df1)+aes(x=Result,y=FSP)+geom_boxplot()
df <- RG_WIMB2013 %>%
select(Player1,Player2,Result,FSP.1,FSP.2,Tournament) %>%
mutate(FSP.W=FSP.1*(Result==1)+FSP.2*(Result==0),FSP.L=FSP.1*(Result==0)+FSP.2*(Result==1))
ggplot(df)+aes(x=Tournament,y=FSP.W)+geom_boxplot()